1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package java.io;
27
28 import java.io.ObjectStreamClass.WeakClassKey;
29 import java.lang.ref.ReferenceQueue;
30 import java.lang.reflect.Array;
31 import java.lang.reflect.Modifier;
32 import java.lang.reflect.Proxy;
33 import java.security.AccessControlContext;
34 import java.security.AccessController;
35 import java.security.PrivilegedAction;
36 import java.security.PrivilegedActionException;
37 import java.security.PrivilegedExceptionAction;
38 import java.util.Arrays;
39 import java.util.HashMap;
40 import java.util.concurrent.ConcurrentHashMap;
41 import java.util.concurrent.ConcurrentMap;
42 import java.util.concurrent.atomic.AtomicBoolean;
43 import static java.io.ObjectStreamClass.processQueue;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205 public class ObjectInputStream
206 extends InputStream implements ObjectInput, ObjectStreamConstants
207 {
208
209 private static final int NULL_HANDLE = -1;
210
211
212 private static final Object unsharedMarker = new Object();
213
214
215 private static final HashMap<String, Class<?>> primClasses
216 = new HashMap<>(8, 1.0F);
217 static {
218 primClasses.put("boolean", boolean.class);
219 primClasses.put("byte", byte.class);
220 primClasses.put("char", char.class);
221 primClasses.put("short", short.class);
222 primClasses.put("int", int.class);
223 primClasses.put("long", long.class);
224 primClasses.put("float", float.class);
225 primClasses.put("double", double.class);
226 primClasses.put("void", void.class);
227 }
228
229 private static class Caches {
230
231 static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
232 new ConcurrentHashMap<>();
233
234
235 static final ReferenceQueue<Class<?>> subclassAuditsQueue =
236 new ReferenceQueue<>();
237 }
238
239
240 private final BlockDataInputStream bin;
241
242 private final ValidationList vlist;
243
244 private int depth;
245
246 private boolean closed;
247
248
249 private final HandleTable handles;
250
251 private int passHandle = NULL_HANDLE;
252
253 private boolean defaultDataEnd = false;
254
255
256 private byte[] primVals;
257
258
259 private final boolean enableOverride;
260
261 private boolean enableResolve;
262
263
264
265
266
267
268 private SerialCallbackContext curContext;
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292 public ObjectInputStream(InputStream in) throws IOException {
293 verifySubclass();
294 bin = new BlockDataInputStream(in);
295 handles = new HandleTable(10);
296 vlist = new ValidationList();
297 enableOverride = false;
298 readStreamHeader();
299 bin.setBlockDataMode(true);
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 protected ObjectInputStream() throws IOException, SecurityException {
319 SecurityManager sm = System.getSecurityManager();
320 if (sm != null) {
321 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
322 }
323 bin = null;
324 handles = null;
325 vlist = null;
326 enableOverride = true;
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359 public final Object readObject()
360 throws IOException, ClassNotFoundException
361 {
362 if (enableOverride) {
363 return readObjectOverride();
364 }
365
366
367 int outerHandle = passHandle;
368 try {
369 Object obj = readObject0(false);
370 handles.markDependency(outerHandle, passHandle);
371 ClassNotFoundException ex = handles.lookupException(passHandle);
372 if (ex != null) {
373 throw ex;
374 }
375 if (depth == 0) {
376 vlist.doCallbacks();
377 }
378 return obj;
379 } finally {
380 passHandle = outerHandle;
381 if (closed && depth == 0) {
382 clear();
383 }
384 }
385 }
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404 protected Object readObjectOverride()
405 throws IOException, ClassNotFoundException
406 {
407 return null;
408 }
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455 public Object readUnshared() throws IOException, ClassNotFoundException {
456
457 int outerHandle = passHandle;
458 try {
459 Object obj = readObject0(true);
460 handles.markDependency(outerHandle, passHandle);
461 ClassNotFoundException ex = handles.lookupException(passHandle);
462 if (ex != null) {
463 throw ex;
464 }
465 if (depth == 0) {
466 vlist.doCallbacks();
467 }
468 return obj;
469 } finally {
470 passHandle = outerHandle;
471 if (closed && depth == 0) {
472 clear();
473 }
474 }
475 }
476
477
478
479
480
481
482
483
484
485
486
487
488
489 public void defaultReadObject()
490 throws IOException, ClassNotFoundException
491 {
492 if (curContext == null) {
493 throw new NotActiveException("not in call to readObject");
494 }
495 Object curObj = curContext.getObj();
496 ObjectStreamClass curDesc = curContext.getDesc();
497 bin.setBlockDataMode(false);
498 defaultReadFields(curObj, curDesc);
499 bin.setBlockDataMode(true);
500 if (!curDesc.hasWriteObjectData()) {
501
502
503
504
505
506 defaultDataEnd = true;
507 }
508 ClassNotFoundException ex = handles.lookupException(passHandle);
509 if (ex != null) {
510 throw ex;
511 }
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527 public ObjectInputStream.GetField readFields()
528 throws IOException, ClassNotFoundException
529 {
530 if (curContext == null) {
531 throw new NotActiveException("not in call to readObject");
532 }
533 Object curObj = curContext.getObj();
534 ObjectStreamClass curDesc = curContext.getDesc();
535 bin.setBlockDataMode(false);
536 GetFieldImpl getField = new GetFieldImpl(curDesc);
537 getField.readFields();
538 bin.setBlockDataMode(true);
539 if (!curDesc.hasWriteObjectData()) {
540
541
542
543
544
545 defaultDataEnd = true;
546 }
547
548 return getField;
549 }
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567 public void registerValidation(ObjectInputValidation obj, int prio)
568 throws NotActiveException, InvalidObjectException
569 {
570 if (depth == 0) {
571 throw new NotActiveException("stream inactive");
572 }
573 vlist.register(obj, prio);
574 }
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617 protected Class<?> resolveClass(ObjectStreamClass desc)
618 throws IOException, ClassNotFoundException
619 {
620 String name = desc.getName();
621 try {
622 return Class.forName(name, false, latestUserDefinedLoader());
623 } catch (ClassNotFoundException ex) {
624 Class<?> cl = primClasses.get(name);
625 if (cl != null) {
626 return cl;
627 } else {
628 throw ex;
629 }
630 }
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684 protected Class<?> resolveProxyClass(String[] interfaces)
685 throws IOException, ClassNotFoundException
686 {
687 ClassLoader latestLoader = latestUserDefinedLoader();
688 ClassLoader nonPublicLoader = null;
689 boolean hasNonPublicInterface = false;
690
691
692 Class[] classObjs = new Class[interfaces.length];
693 for (int i = 0; i < interfaces.length; i++) {
694 Class cl = Class.forName(interfaces[i], false, latestLoader);
695 if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
696 if (hasNonPublicInterface) {
697 if (nonPublicLoader != cl.getClassLoader()) {
698 throw new IllegalAccessError(
699 "conflicting non-public interface class loaders");
700 }
701 } else {
702 nonPublicLoader = cl.getClassLoader();
703 hasNonPublicInterface = true;
704 }
705 }
706 classObjs[i] = cl;
707 }
708 try {
709 return Proxy.getProxyClass(
710 hasNonPublicInterface ? nonPublicLoader : latestLoader,
711 classObjs);
712 } catch (IllegalArgumentException e) {
713 throw new ClassNotFoundException(null, e);
714 }
715 }
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744 protected Object resolveObject(Object obj) throws IOException {
745 return obj;
746 }
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769 protected boolean enableResolveObject(boolean enable)
770 throws SecurityException
771 {
772 if (enable == enableResolve) {
773 return enable;
774 }
775 if (enable) {
776 SecurityManager sm = System.getSecurityManager();
777 if (sm != null) {
778 sm.checkPermission(SUBSTITUTION_PERMISSION);
779 }
780 }
781 enableResolve = enable;
782 return !enableResolve;
783 }
784
785
786
787
788
789
790
791
792
793
794
795 protected void readStreamHeader()
796 throws IOException, StreamCorruptedException
797 {
798 short s0 = bin.readShort();
799 short s1 = bin.readShort();
800 if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
801 throw new StreamCorruptedException(
802 String.format("invalid stream header: %04X%04X", s0, s1));
803 }
804 }
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823 protected ObjectStreamClass readClassDescriptor()
824 throws IOException, ClassNotFoundException
825 {
826 ObjectStreamClass desc = new ObjectStreamClass();
827 desc.readNonProxy(this);
828 return desc;
829 }
830
831
832
833
834
835
836
837 public int read() throws IOException {
838 return bin.read();
839 }
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854 public int read(byte[] buf, int off, int len) throws IOException {
855 if (buf == null) {
856 throw new NullPointerException();
857 }
858 int endoff = off + len;
859 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
860 throw new IndexOutOfBoundsException();
861 }
862 return bin.read(buf, off, len, false);
863 }
864
865
866
867
868
869
870
871
872 public int available() throws IOException {
873 return bin.available();
874 }
875
876
877
878
879
880
881
882 public void close() throws IOException {
883
884
885
886
887 closed = true;
888 if (depth == 0) {
889 clear();
890 }
891 bin.close();
892 }
893
894
895
896
897
898
899
900
901 public boolean readBoolean() throws IOException {
902 return bin.readBoolean();
903 }
904
905
906
907
908
909
910
911
912 public byte readByte() throws IOException {
913 return bin.readByte();
914 }
915
916
917
918
919
920
921
922
923 public int readUnsignedByte() throws IOException {
924 return bin.readUnsignedByte();
925 }
926
927
928
929
930
931
932
933
934 public char readChar() throws IOException {
935 return bin.readChar();
936 }
937
938
939
940
941
942
943
944
945 public short readShort() throws IOException {
946 return bin.readShort();
947 }
948
949
950
951
952
953
954
955
956 public int readUnsignedShort() throws IOException {
957 return bin.readUnsignedShort();
958 }
959
960
961
962
963
964
965
966
967 public int readInt() throws IOException {
968 return bin.readInt();
969 }
970
971
972
973
974
975
976
977
978 public long readLong() throws IOException {
979 return bin.readLong();
980 }
981
982
983
984
985
986
987
988
989 public float readFloat() throws IOException {
990 return bin.readFloat();
991 }
992
993
994
995
996
997
998
999
1000 public double readDouble() throws IOException {
1001 return bin.readDouble();
1002 }
1003
1004
1005
1006
1007
1008
1009
1010
1011 public void readFully(byte[] buf) throws IOException {
1012 bin.readFully(buf, 0, buf.length, false);
1013 }
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024 public void readFully(byte[] buf, int off, int len) throws IOException {
1025 int endoff = off + len;
1026 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
1027 throw new IndexOutOfBoundsException();
1028 }
1029 bin.readFully(buf, off, len, false);
1030 }
1031
1032
1033
1034
1035
1036
1037
1038
1039 public int skipBytes(int len) throws IOException {
1040 return bin.skipBytes(len);
1041 }
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052 @Deprecated
1053 public String readLine() throws IOException {
1054 return bin.readLine();
1055 }
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 public String readUTF() throws IOException {
1069 return bin.readUTF();
1070 }
1071
1072
1073
1074
1075 public static abstract class GetField {
1076
1077
1078
1079
1080
1081
1082 public abstract ObjectStreamClass getObjectStreamClass();
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095 public abstract boolean defaulted(String name) throws IOException;
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109 public abstract boolean get(String name, boolean val)
1110 throws IOException;
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124 public abstract byte get(String name, byte val) throws IOException;
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138 public abstract char get(String name, char val) throws IOException;
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152 public abstract short get(String name, short val) throws IOException;
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166 public abstract int get(String name, int val) throws IOException;
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180 public abstract long get(String name, long val) throws IOException;
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 public abstract float get(String name, float val) throws IOException;
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208 public abstract double get(String name, double val) throws IOException;
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222 public abstract Object get(String name, Object val) throws IOException;
1223 }
1224
1225
1226
1227
1228
1229
1230
1231 private void verifySubclass() {
1232 Class cl = getClass();
1233 if (cl == ObjectInputStream.class) {
1234 return;
1235 }
1236 SecurityManager sm = System.getSecurityManager();
1237 if (sm == null) {
1238 return;
1239 }
1240 processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
1241 WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
1242 Boolean result = Caches.subclassAudits.get(key);
1243 if (result == null) {
1244 result = Boolean.valueOf(auditSubclass(cl));
1245 Caches.subclassAudits.putIfAbsent(key, result);
1246 }
1247 if (result.booleanValue()) {
1248 return;
1249 }
1250 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
1251 }
1252
1253
1254
1255
1256
1257
1258 private static boolean auditSubclass(final Class<?> subcl) {
1259 Boolean result = AccessController.doPrivileged(
1260 new PrivilegedAction<Boolean>() {
1261 public Boolean run() {
1262 for (Class<?> cl = subcl;
1263 cl != ObjectInputStream.class;
1264 cl = cl.getSuperclass())
1265 {
1266 try {
1267 cl.getDeclaredMethod(
1268 "readUnshared", (Class[]) null);
1269 return Boolean.FALSE;
1270 } catch (NoSuchMethodException ex) {
1271 }
1272 try {
1273 cl.getDeclaredMethod("readFields", (Class[]) null);
1274 return Boolean.FALSE;
1275 } catch (NoSuchMethodException ex) {
1276 }
1277 }
1278 return Boolean.TRUE;
1279 }
1280 }
1281 );
1282 return result.booleanValue();
1283 }
1284
1285
1286
1287
1288 private void clear() {
1289 handles.clear();
1290 vlist.clear();
1291 }
1292
1293
1294
1295
1296 private Object readObject0(boolean unshared) throws IOException {
1297 boolean oldMode = bin.getBlockDataMode();
1298 if (oldMode) {
1299 int remain = bin.currentBlockRemaining();
1300 if (remain > 0) {
1301 throw new OptionalDataException(remain);
1302 } else if (defaultDataEnd) {
1303
1304
1305
1306
1307
1308
1309 throw new OptionalDataException(true);
1310 }
1311 bin.setBlockDataMode(false);
1312 }
1313
1314 byte tc;
1315 while ((tc = bin.peekByte()) == TC_RESET) {
1316 bin.readByte();
1317 handleReset();
1318 }
1319
1320 depth++;
1321 try {
1322 switch (tc) {
1323 case TC_NULL:
1324 return readNull();
1325
1326 case TC_REFERENCE:
1327 return readHandle(unshared);
1328
1329 case TC_CLASS:
1330 return readClass(unshared);
1331
1332 case TC_CLASSDESC:
1333 case TC_PROXYCLASSDESC:
1334 return readClassDesc(unshared);
1335
1336 case TC_STRING:
1337 case TC_LONGSTRING:
1338 return checkResolve(readString(unshared));
1339
1340 case TC_ARRAY:
1341 return checkResolve(readArray(unshared));
1342
1343 case TC_ENUM:
1344 return checkResolve(readEnum(unshared));
1345
1346 case TC_OBJECT:
1347 return checkResolve(readOrdinaryObject(unshared));
1348
1349 case TC_EXCEPTION:
1350 IOException ex = readFatalException();
1351 throw new WriteAbortedException("writing aborted", ex);
1352
1353 case TC_BLOCKDATA:
1354 case TC_BLOCKDATALONG:
1355 if (oldMode) {
1356 bin.setBlockDataMode(true);
1357 bin.peek();
1358 throw new OptionalDataException(
1359 bin.currentBlockRemaining());
1360 } else {
1361 throw new StreamCorruptedException(
1362 "unexpected block data");
1363 }
1364
1365 case TC_ENDBLOCKDATA:
1366 if (oldMode) {
1367 throw new OptionalDataException(true);
1368 } else {
1369 throw new StreamCorruptedException(
1370 "unexpected end of block data");
1371 }
1372
1373 default:
1374 throw new StreamCorruptedException(
1375 String.format("invalid type code: %02X", tc));
1376 }
1377 } finally {
1378 depth--;
1379 bin.setBlockDataMode(oldMode);
1380 }
1381 }
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391 private Object checkResolve(Object obj) throws IOException {
1392 if (!enableResolve || handles.lookupException(passHandle) != null) {
1393 return obj;
1394 }
1395 Object rep = resolveObject(obj);
1396 if (rep != obj) {
1397 handles.setObject(passHandle, rep);
1398 }
1399 return rep;
1400 }
1401
1402
1403
1404
1405
1406 String readTypeString() throws IOException {
1407 int oldHandle = passHandle;
1408 try {
1409 byte tc = bin.peekByte();
1410 switch (tc) {
1411 case TC_NULL:
1412 return (String) readNull();
1413
1414 case TC_REFERENCE:
1415 return (String) readHandle(false);
1416
1417 case TC_STRING:
1418 case TC_LONGSTRING:
1419 return readString(false);
1420
1421 default:
1422 throw new StreamCorruptedException(
1423 String.format("invalid type code: %02X", tc));
1424 }
1425 } finally {
1426 passHandle = oldHandle;
1427 }
1428 }
1429
1430
1431
1432
1433 private Object readNull() throws IOException {
1434 if (bin.readByte() != TC_NULL) {
1435 throw new InternalError();
1436 }
1437 passHandle = NULL_HANDLE;
1438 return null;
1439 }
1440
1441
1442
1443
1444
1445 private Object readHandle(boolean unshared) throws IOException {
1446 if (bin.readByte() != TC_REFERENCE) {
1447 throw new InternalError();
1448 }
1449 passHandle = bin.readInt() - baseWireHandle;
1450 if (passHandle < 0 || passHandle >= handles.size()) {
1451 throw new StreamCorruptedException(
1452 String.format("invalid handle value: %08X", passHandle +
1453 baseWireHandle));
1454 }
1455 if (unshared) {
1456
1457 throw new InvalidObjectException(
1458 "cannot read back reference as unshared");
1459 }
1460
1461 Object obj = handles.lookupObject(passHandle);
1462 if (obj == unsharedMarker) {
1463
1464 throw new InvalidObjectException(
1465 "cannot read back reference to unshared object");
1466 }
1467 return obj;
1468 }
1469
1470
1471
1472
1473
1474
1475
1476 private Class readClass(boolean unshared) throws IOException {
1477 if (bin.readByte() != TC_CLASS) {
1478 throw new InternalError();
1479 }
1480 ObjectStreamClass desc = readClassDesc(false);
1481 Class cl = desc.forClass();
1482 passHandle = handles.assign(unshared ? unsharedMarker : cl);
1483
1484 ClassNotFoundException resolveEx = desc.getResolveException();
1485 if (resolveEx != null) {
1486 handles.markException(passHandle, resolveEx);
1487 }
1488
1489 handles.finish(passHandle);
1490 return cl;
1491 }
1492
1493
1494
1495
1496
1497
1498
1499 private ObjectStreamClass readClassDesc(boolean unshared)
1500 throws IOException
1501 {
1502 byte tc = bin.peekByte();
1503 switch (tc) {
1504 case TC_NULL:
1505 return (ObjectStreamClass) readNull();
1506
1507 case TC_REFERENCE:
1508 return (ObjectStreamClass) readHandle(unshared);
1509
1510 case TC_PROXYCLASSDESC:
1511 return readProxyDesc(unshared);
1512
1513 case TC_CLASSDESC:
1514 return readNonProxyDesc(unshared);
1515
1516 default:
1517 throw new StreamCorruptedException(
1518 String.format("invalid type code: %02X", tc));
1519 }
1520 }
1521
1522
1523
1524
1525
1526
1527
1528 private ObjectStreamClass readProxyDesc(boolean unshared)
1529 throws IOException
1530 {
1531 if (bin.readByte() != TC_PROXYCLASSDESC) {
1532 throw new InternalError();
1533 }
1534
1535 ObjectStreamClass desc = new ObjectStreamClass();
1536 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1537 passHandle = NULL_HANDLE;
1538
1539 int numIfaces = bin.readInt();
1540 String[] ifaces = new String[numIfaces];
1541 for (int i = 0; i < numIfaces; i++) {
1542 ifaces[i] = bin.readUTF();
1543 }
1544
1545 Class cl = null;
1546 ClassNotFoundException resolveEx = null;
1547 bin.setBlockDataMode(true);
1548 try {
1549 if ((cl = resolveProxyClass(ifaces)) == null) {
1550 resolveEx = new ClassNotFoundException("null class");
1551 }
1552 } catch (ClassNotFoundException ex) {
1553 resolveEx = ex;
1554 }
1555 skipCustomData();
1556
1557 desc.initProxy(cl, resolveEx, readClassDesc(false));
1558
1559 handles.finish(descHandle);
1560 passHandle = descHandle;
1561 return desc;
1562 }
1563
1564
1565
1566
1567
1568
1569
1570 private ObjectStreamClass readNonProxyDesc(boolean unshared)
1571 throws IOException
1572 {
1573 if (bin.readByte() != TC_CLASSDESC) {
1574 throw new InternalError();
1575 }
1576
1577 ObjectStreamClass desc = new ObjectStreamClass();
1578 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1579 passHandle = NULL_HANDLE;
1580
1581 ObjectStreamClass readDesc = null;
1582 try {
1583 readDesc = readClassDescriptor();
1584 } catch (ClassNotFoundException ex) {
1585 throw (IOException) new InvalidClassException(
1586 "failed to read class descriptor").initCause(ex);
1587 }
1588
1589 Class cl = null;
1590 ClassNotFoundException resolveEx = null;
1591 bin.setBlockDataMode(true);
1592 try {
1593 if ((cl = resolveClass(readDesc)) == null) {
1594 resolveEx = new ClassNotFoundException("null class");
1595 }
1596 } catch (ClassNotFoundException ex) {
1597 resolveEx = ex;
1598 }
1599 skipCustomData();
1600
1601 desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
1602
1603 handles.finish(descHandle);
1604 passHandle = descHandle;
1605 return desc;
1606 }
1607
1608
1609
1610
1611
1612 private String readString(boolean unshared) throws IOException {
1613 String str;
1614 byte tc = bin.readByte();
1615 switch (tc) {
1616 case TC_STRING:
1617 str = bin.readUTF();
1618 break;
1619
1620 case TC_LONGSTRING:
1621 str = bin.readLongUTF();
1622 break;
1623
1624 default:
1625 throw new StreamCorruptedException(
1626 String.format("invalid type code: %02X", tc));
1627 }
1628 passHandle = handles.assign(unshared ? unsharedMarker : str);
1629 handles.finish(passHandle);
1630 return str;
1631 }
1632
1633
1634
1635
1636
1637 private Object readArray(boolean unshared) throws IOException {
1638 if (bin.readByte() != TC_ARRAY) {
1639 throw new InternalError();
1640 }
1641
1642 ObjectStreamClass desc = readClassDesc(false);
1643 int len = bin.readInt();
1644
1645 Object array = null;
1646 Class cl, ccl = null;
1647 if ((cl = desc.forClass()) != null) {
1648 ccl = cl.getComponentType();
1649 array = Array.newInstance(ccl, len);
1650 }
1651
1652 int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
1653 ClassNotFoundException resolveEx = desc.getResolveException();
1654 if (resolveEx != null) {
1655 handles.markException(arrayHandle, resolveEx);
1656 }
1657
1658 if (ccl == null) {
1659 for (int i = 0; i < len; i++) {
1660 readObject0(false);
1661 }
1662 } else if (ccl.isPrimitive()) {
1663 if (ccl == Integer.TYPE) {
1664 bin.readInts((int[]) array, 0, len);
1665 } else if (ccl == Byte.TYPE) {
1666 bin.readFully((byte[]) array, 0, len, true);
1667 } else if (ccl == Long.TYPE) {
1668 bin.readLongs((long[]) array, 0, len);
1669 } else if (ccl == Float.TYPE) {
1670 bin.readFloats((float[]) array, 0, len);
1671 } else if (ccl == Double.TYPE) {
1672 bin.readDoubles((double[]) array, 0, len);
1673 } else if (ccl == Short.TYPE) {
1674 bin.readShorts((short[]) array, 0, len);
1675 } else if (ccl == Character.TYPE) {
1676 bin.readChars((char[]) array, 0, len);
1677 } else if (ccl == Boolean.TYPE) {
1678 bin.readBooleans((boolean[]) array, 0, len);
1679 } else {
1680 throw new InternalError();
1681 }
1682 } else {
1683 Object[] oa = (Object[]) array;
1684 for (int i = 0; i < len; i++) {
1685 oa[i] = readObject0(false);
1686 handles.markDependency(arrayHandle, passHandle);
1687 }
1688 }
1689
1690 handles.finish(arrayHandle);
1691 passHandle = arrayHandle;
1692 return array;
1693 }
1694
1695
1696
1697
1698
1699 private Enum readEnum(boolean unshared) throws IOException {
1700 if (bin.readByte() != TC_ENUM) {
1701 throw new InternalError();
1702 }
1703
1704 ObjectStreamClass desc = readClassDesc(false);
1705 if (!desc.isEnum()) {
1706 throw new InvalidClassException("non-enum class: " + desc);
1707 }
1708
1709 int enumHandle = handles.assign(unshared ? unsharedMarker : null);
1710 ClassNotFoundException resolveEx = desc.getResolveException();
1711 if (resolveEx != null) {
1712 handles.markException(enumHandle, resolveEx);
1713 }
1714
1715 String name = readString(false);
1716 Enum en = null;
1717 Class cl = desc.forClass();
1718 if (cl != null) {
1719 try {
1720 en = Enum.valueOf(cl, name);
1721 } catch (IllegalArgumentException ex) {
1722 throw (IOException) new InvalidObjectException(
1723 "enum constant " + name + " does not exist in " +
1724 cl).initCause(ex);
1725 }
1726 if (!unshared) {
1727 handles.setObject(enumHandle, en);
1728 }
1729 }
1730
1731 handles.finish(enumHandle);
1732 passHandle = enumHandle;
1733 return en;
1734 }
1735
1736
1737
1738
1739
1740
1741
1742
1743 private Object readOrdinaryObject(boolean unshared)
1744 throws IOException
1745 {
1746 if (bin.readByte() != TC_OBJECT) {
1747 throw new InternalError();
1748 }
1749
1750 ObjectStreamClass desc = readClassDesc(false);
1751 desc.checkDeserialize();
1752
1753 Object obj;
1754 try {
1755 obj = desc.isInstantiable() ? desc.newInstance() : null;
1756 } catch (Exception ex) {
1757 throw (IOException) new InvalidClassException(
1758 desc.forClass().getName(),
1759 "unable to create instance").initCause(ex);
1760 }
1761
1762 passHandle = handles.assign(unshared ? unsharedMarker : obj);
1763 ClassNotFoundException resolveEx = desc.getResolveException();
1764 if (resolveEx != null) {
1765 handles.markException(passHandle, resolveEx);
1766 }
1767
1768 if (desc.isExternalizable()) {
1769 readExternalData((Externalizable) obj, desc);
1770 } else {
1771 readSerialData(obj, desc);
1772 }
1773
1774 handles.finish(passHandle);
1775
1776 if (obj != null &&
1777 handles.lookupException(passHandle) == null &&
1778 desc.hasReadResolveMethod())
1779 {
1780 Object rep = desc.invokeReadResolve(obj);
1781 if (unshared && rep.getClass().isArray()) {
1782 rep = cloneArray(rep);
1783 }
1784 if (rep != obj) {
1785 handles.setObject(passHandle, obj = rep);
1786 }
1787 }
1788
1789 return obj;
1790 }
1791
1792
1793
1794
1795
1796
1797
1798 private void readExternalData(Externalizable obj, ObjectStreamClass desc)
1799 throws IOException
1800 {
1801 SerialCallbackContext oldContext = curContext;
1802 curContext = null;
1803 try {
1804 boolean blocked = desc.hasBlockExternalData();
1805 if (blocked) {
1806 bin.setBlockDataMode(true);
1807 }
1808 if (obj != null) {
1809 try {
1810 obj.readExternal(this);
1811 } catch (ClassNotFoundException ex) {
1812
1813
1814
1815
1816
1817
1818
1819 handles.markException(passHandle, ex);
1820 }
1821 }
1822 if (blocked) {
1823 skipCustomData();
1824 }
1825 } finally {
1826 curContext = oldContext;
1827 }
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840 }
1841
1842
1843
1844
1845
1846
1847
1848 private void readSerialData(Object obj, ObjectStreamClass desc)
1849 throws IOException
1850 {
1851 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
1852 for (int i = 0; i < slots.length; i++) {
1853 ObjectStreamClass slotDesc = slots[i].desc;
1854
1855 if (slots[i].hasData) {
1856 if (obj != null &&
1857 slotDesc.hasReadObjectMethod() &&
1858 handles.lookupException(passHandle) == null)
1859 {
1860 SerialCallbackContext oldContext = curContext;
1861
1862 try {
1863 curContext = new SerialCallbackContext(obj, slotDesc);
1864
1865 bin.setBlockDataMode(true);
1866 slotDesc.invokeReadObject(obj, this);
1867 } catch (ClassNotFoundException ex) {
1868
1869
1870
1871
1872
1873
1874
1875 handles.markException(passHandle, ex);
1876 } finally {
1877 curContext.setUsed();
1878 curContext = oldContext;
1879 }
1880
1881
1882
1883
1884
1885
1886 defaultDataEnd = false;
1887 } else {
1888 defaultReadFields(obj, slotDesc);
1889 }
1890 if (slotDesc.hasWriteObjectData()) {
1891 skipCustomData();
1892 } else {
1893 bin.setBlockDataMode(false);
1894 }
1895 } else {
1896 if (obj != null &&
1897 slotDesc.hasReadObjectNoDataMethod() &&
1898 handles.lookupException(passHandle) == null)
1899 {
1900 slotDesc.invokeReadObjectNoData(obj);
1901 }
1902 }
1903 }
1904 }
1905
1906
1907
1908
1909
1910 private void skipCustomData() throws IOException {
1911 int oldHandle = passHandle;
1912 for (;;) {
1913 if (bin.getBlockDataMode()) {
1914 bin.skipBlockData();
1915 bin.setBlockDataMode(false);
1916 }
1917 switch (bin.peekByte()) {
1918 case TC_BLOCKDATA:
1919 case TC_BLOCKDATALONG:
1920 bin.setBlockDataMode(true);
1921 break;
1922
1923 case TC_ENDBLOCKDATA:
1924 bin.readByte();
1925 passHandle = oldHandle;
1926 return;
1927
1928 default:
1929 readObject0(false);
1930 break;
1931 }
1932 }
1933 }
1934
1935
1936
1937
1938
1939
1940 private void defaultReadFields(Object obj, ObjectStreamClass desc)
1941 throws IOException
1942 {
1943
1944 Class cl = desc.forClass();
1945 if (cl != null && obj != null && !cl.isInstance(obj)) {
1946 throw new ClassCastException();
1947 }
1948
1949 int primDataSize = desc.getPrimDataSize();
1950 if (primVals == null || primVals.length < primDataSize) {
1951 primVals = new byte[primDataSize];
1952 }
1953 bin.readFully(primVals, 0, primDataSize, false);
1954 if (obj != null) {
1955 desc.setPrimFieldValues(obj, primVals);
1956 }
1957
1958 int objHandle = passHandle;
1959 ObjectStreamField[] fields = desc.getFields(false);
1960 Object[] objVals = new Object[desc.getNumObjFields()];
1961 int numPrimFields = fields.length - objVals.length;
1962 for (int i = 0; i < objVals.length; i++) {
1963 ObjectStreamField f = fields[numPrimFields + i];
1964 objVals[i] = readObject0(f.isUnshared());
1965 if (f.getField() != null) {
1966 handles.markDependency(objHandle, passHandle);
1967 }
1968 }
1969 if (obj != null) {
1970 desc.setObjFieldValues(obj, objVals);
1971 }
1972 passHandle = objHandle;
1973 }
1974
1975
1976
1977
1978
1979
1980 private IOException readFatalException() throws IOException {
1981 if (bin.readByte() != TC_EXCEPTION) {
1982 throw new InternalError();
1983 }
1984 clear();
1985 return (IOException) readObject0(false);
1986 }
1987
1988
1989
1990
1991
1992
1993 private void handleReset() throws StreamCorruptedException {
1994 if (depth > 0) {
1995 throw new StreamCorruptedException(
1996 "unexpected reset; recursion depth: " + depth);
1997 }
1998 clear();
1999 }
2000
2001
2002
2003
2004
2005 private static native void bytesToFloats(byte[] src, int srcpos,
2006 float[] dst, int dstpos,
2007 int nfloats);
2008
2009
2010
2011
2012
2013 private static native void bytesToDoubles(byte[] src, int srcpos,
2014 double[] dst, int dstpos,
2015 int ndoubles);
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029 private static native ClassLoader latestUserDefinedLoader();
2030
2031
2032
2033
2034 private class GetFieldImpl extends GetField {
2035
2036
2037 private final ObjectStreamClass desc;
2038
2039 private final byte[] primVals;
2040
2041 private final Object[] objVals;
2042
2043 private final int[] objHandles;
2044
2045
2046
2047
2048
2049 GetFieldImpl(ObjectStreamClass desc) {
2050 this.desc = desc;
2051 primVals = new byte[desc.getPrimDataSize()];
2052 objVals = new Object[desc.getNumObjFields()];
2053 objHandles = new int[objVals.length];
2054 }
2055
2056 public ObjectStreamClass getObjectStreamClass() {
2057 return desc;
2058 }
2059
2060 public boolean defaulted(String name) throws IOException {
2061 return (getFieldOffset(name, null) < 0);
2062 }
2063
2064 public boolean get(String name, boolean val) throws IOException {
2065 int off = getFieldOffset(name, Boolean.TYPE);
2066 return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
2067 }
2068
2069 public byte get(String name, byte val) throws IOException {
2070 int off = getFieldOffset(name, Byte.TYPE);
2071 return (off >= 0) ? primVals[off] : val;
2072 }
2073
2074 public char get(String name, char val) throws IOException {
2075 int off = getFieldOffset(name, Character.TYPE);
2076 return (off >= 0) ? Bits.getChar(primVals, off) : val;
2077 }
2078
2079 public short get(String name, short val) throws IOException {
2080 int off = getFieldOffset(name, Short.TYPE);
2081 return (off >= 0) ? Bits.getShort(primVals, off) : val;
2082 }
2083
2084 public int get(String name, int val) throws IOException {
2085 int off = getFieldOffset(name, Integer.TYPE);
2086 return (off >= 0) ? Bits.getInt(primVals, off) : val;
2087 }
2088
2089 public float get(String name, float val) throws IOException {
2090 int off = getFieldOffset(name, Float.TYPE);
2091 return (off >= 0) ? Bits.getFloat(primVals, off) : val;
2092 }
2093
2094 public long get(String name, long val) throws IOException {
2095 int off = getFieldOffset(name, Long.TYPE);
2096 return (off >= 0) ? Bits.getLong(primVals, off) : val;
2097 }
2098
2099 public double get(String name, double val) throws IOException {
2100 int off = getFieldOffset(name, Double.TYPE);
2101 return (off >= 0) ? Bits.getDouble(primVals, off) : val;
2102 }
2103
2104 public Object get(String name, Object val) throws IOException {
2105 int off = getFieldOffset(name, Object.class);
2106 if (off >= 0) {
2107 int objHandle = objHandles[off];
2108 handles.markDependency(passHandle, objHandle);
2109 return (handles.lookupException(objHandle) == null) ?
2110 objVals[off] : null;
2111 } else {
2112 return val;
2113 }
2114 }
2115
2116
2117
2118
2119 void readFields() throws IOException {
2120 bin.readFully(primVals, 0, primVals.length, false);
2121
2122 int oldHandle = passHandle;
2123 ObjectStreamField[] fields = desc.getFields(false);
2124 int numPrimFields = fields.length - objVals.length;
2125 for (int i = 0; i < objVals.length; i++) {
2126 objVals[i] =
2127 readObject0(fields[numPrimFields + i].isUnshared());
2128 objHandles[i] = passHandle;
2129 }
2130 passHandle = oldHandle;
2131 }
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142 private int getFieldOffset(String name, Class type) {
2143 ObjectStreamField field = desc.getField(name, type);
2144 if (field != null) {
2145 return field.getOffset();
2146 } else if (desc.getLocalDesc().getField(name, type) != null) {
2147 return -1;
2148 } else {
2149 throw new IllegalArgumentException("no such field " + name +
2150 " with type " + type);
2151 }
2152 }
2153 }
2154
2155
2156
2157
2158
2159 private static class ValidationList {
2160
2161 private static class Callback {
2162 final ObjectInputValidation obj;
2163 final int priority;
2164 Callback next;
2165 final AccessControlContext acc;
2166
2167 Callback(ObjectInputValidation obj, int priority, Callback next,
2168 AccessControlContext acc)
2169 {
2170 this.obj = obj;
2171 this.priority = priority;
2172 this.next = next;
2173 this.acc = acc;
2174 }
2175 }
2176
2177
2178 private Callback list;
2179
2180
2181
2182
2183 ValidationList() {
2184 }
2185
2186
2187
2188
2189
2190 void register(ObjectInputValidation obj, int priority)
2191 throws InvalidObjectException
2192 {
2193 if (obj == null) {
2194 throw new InvalidObjectException("null callback");
2195 }
2196
2197 Callback prev = null, cur = list;
2198 while (cur != null && priority < cur.priority) {
2199 prev = cur;
2200 cur = cur.next;
2201 }
2202 AccessControlContext acc = AccessController.getContext();
2203 if (prev != null) {
2204 prev.next = new Callback(obj, priority, cur, acc);
2205 } else {
2206 list = new Callback(obj, priority, list, acc);
2207 }
2208 }
2209
2210
2211
2212
2213
2214
2215
2216
2217 void doCallbacks() throws InvalidObjectException {
2218 try {
2219 while (list != null) {
2220 AccessController.doPrivileged(
2221 new PrivilegedExceptionAction<Void>()
2222 {
2223 public Void run() throws InvalidObjectException {
2224 list.obj.validateObject();
2225 return null;
2226 }
2227 }, list.acc);
2228 list = list.next;
2229 }
2230 } catch (PrivilegedActionException ex) {
2231 list = null;
2232 throw (InvalidObjectException) ex.getException();
2233 }
2234 }
2235
2236
2237
2238
2239 public void clear() {
2240 list = null;
2241 }
2242 }
2243
2244
2245
2246
2247 private static class PeekInputStream extends InputStream {
2248
2249
2250 private final InputStream in;
2251
2252 private int peekb = -1;
2253
2254
2255
2256
2257 PeekInputStream(InputStream in) {
2258 this.in = in;
2259 }
2260
2261
2262
2263
2264
2265 int peek() throws IOException {
2266 return (peekb >= 0) ? peekb : (peekb = in.read());
2267 }
2268
2269 public int read() throws IOException {
2270 if (peekb >= 0) {
2271 int v = peekb;
2272 peekb = -1;
2273 return v;
2274 } else {
2275 return in.read();
2276 }
2277 }
2278
2279 public int read(byte[] b, int off, int len) throws IOException {
2280 if (len == 0) {
2281 return 0;
2282 } else if (peekb < 0) {
2283 return in.read(b, off, len);
2284 } else {
2285 b[off++] = (byte) peekb;
2286 len--;
2287 peekb = -1;
2288 int n = in.read(b, off, len);
2289 return (n >= 0) ? (n + 1) : 1;
2290 }
2291 }
2292
2293 void readFully(byte[] b, int off, int len) throws IOException {
2294 int n = 0;
2295 while (n < len) {
2296 int count = read(b, off + n, len - n);
2297 if (count < 0) {
2298 throw new EOFException();
2299 }
2300 n += count;
2301 }
2302 }
2303
2304 public long skip(long n) throws IOException {
2305 if (n <= 0) {
2306 return 0;
2307 }
2308 int skipped = 0;
2309 if (peekb >= 0) {
2310 peekb = -1;
2311 skipped++;
2312 n--;
2313 }
2314 return skipped + skip(n);
2315 }
2316
2317 public int available() throws IOException {
2318 return in.available() + ((peekb >= 0) ? 1 : 0);
2319 }
2320
2321 public void close() throws IOException {
2322 in.close();
2323 }
2324 }
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334 private class BlockDataInputStream
2335 extends InputStream implements DataInput
2336 {
2337
2338 private static final int MAX_BLOCK_SIZE = 1024;
2339
2340 private static final int MAX_HEADER_SIZE = 5;
2341
2342 private static final int CHAR_BUF_SIZE = 256;
2343
2344 private static final int HEADER_BLOCKED = -2;
2345
2346
2347 private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2348
2349 private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2350
2351 private final char[] cbuf = new char[CHAR_BUF_SIZE];
2352
2353
2354 private boolean blkmode = false;
2355
2356
2357
2358 private int pos = 0;
2359
2360 private int end = -1;
2361
2362 private int unread = 0;
2363
2364
2365 private final PeekInputStream in;
2366
2367 private final DataInputStream din;
2368
2369
2370
2371
2372
2373 BlockDataInputStream(InputStream in) {
2374 this.in = new PeekInputStream(in);
2375 din = new DataInputStream(this);
2376 }
2377
2378
2379
2380
2381
2382
2383
2384
2385 boolean setBlockDataMode(boolean newmode) throws IOException {
2386 if (blkmode == newmode) {
2387 return blkmode;
2388 }
2389 if (newmode) {
2390 pos = 0;
2391 end = 0;
2392 unread = 0;
2393 } else if (pos < end) {
2394 throw new IllegalStateException("unread block data");
2395 }
2396 blkmode = newmode;
2397 return !blkmode;
2398 }
2399
2400
2401
2402
2403
2404 boolean getBlockDataMode() {
2405 return blkmode;
2406 }
2407
2408
2409
2410
2411
2412
2413 void skipBlockData() throws IOException {
2414 if (!blkmode) {
2415 throw new IllegalStateException("not in block data mode");
2416 }
2417 while (end >= 0) {
2418 refill();
2419 }
2420 }
2421
2422
2423
2424
2425
2426
2427
2428
2429 private int readBlockHeader(boolean canBlock) throws IOException {
2430 if (defaultDataEnd) {
2431
2432
2433
2434
2435
2436
2437 return -1;
2438 }
2439 try {
2440 for (;;) {
2441 int avail = canBlock ? Integer.MAX_VALUE : in.available();
2442 if (avail == 0) {
2443 return HEADER_BLOCKED;
2444 }
2445
2446 int tc = in.peek();
2447 switch (tc) {
2448 case TC_BLOCKDATA:
2449 if (avail < 2) {
2450 return HEADER_BLOCKED;
2451 }
2452 in.readFully(hbuf, 0, 2);
2453 return hbuf[1] & 0xFF;
2454
2455 case TC_BLOCKDATALONG:
2456 if (avail < 5) {
2457 return HEADER_BLOCKED;
2458 }
2459 in.readFully(hbuf, 0, 5);
2460 int len = Bits.getInt(hbuf, 1);
2461 if (len < 0) {
2462 throw new StreamCorruptedException(
2463 "illegal block data header length: " +
2464 len);
2465 }
2466 return len;
2467
2468
2469
2470
2471
2472
2473
2474 case TC_RESET:
2475 in.read();
2476 handleReset();
2477 break;
2478
2479 default:
2480 if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
2481 throw new StreamCorruptedException(
2482 String.format("invalid type code: %02X",
2483 tc));
2484 }
2485 return -1;
2486 }
2487 }
2488 } catch (EOFException ex) {
2489 throw new StreamCorruptedException(
2490 "unexpected EOF while reading block data header");
2491 }
2492 }
2493
2494
2495
2496
2497
2498
2499
2500
2501 private void refill() throws IOException {
2502 try {
2503 do {
2504 pos = 0;
2505 if (unread > 0) {
2506 int n =
2507 in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
2508 if (n >= 0) {
2509 end = n;
2510 unread -= n;
2511 } else {
2512 throw new StreamCorruptedException(
2513 "unexpected EOF in middle of data block");
2514 }
2515 } else {
2516 int n = readBlockHeader(true);
2517 if (n >= 0) {
2518 end = 0;
2519 unread = n;
2520 } else {
2521 end = -1;
2522 unread = 0;
2523 }
2524 }
2525 } while (pos == end);
2526 } catch (IOException ex) {
2527 pos = 0;
2528 end = -1;
2529 unread = 0;
2530 throw ex;
2531 }
2532 }
2533
2534
2535
2536
2537
2538
2539 int currentBlockRemaining() {
2540 if (blkmode) {
2541 return (end >= 0) ? (end - pos) + unread : 0;
2542 } else {
2543 throw new IllegalStateException();
2544 }
2545 }
2546
2547
2548
2549
2550
2551
2552 int peek() throws IOException {
2553 if (blkmode) {
2554 if (pos == end) {
2555 refill();
2556 }
2557 return (end >= 0) ? (buf[pos] & 0xFF) : -1;
2558 } else {
2559 return in.peek();
2560 }
2561 }
2562
2563
2564
2565
2566
2567
2568 byte peekByte() throws IOException {
2569 int val = peek();
2570 if (val < 0) {
2571 throw new EOFException();
2572 }
2573 return (byte) val;
2574 }
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585 public int read() throws IOException {
2586 if (blkmode) {
2587 if (pos == end) {
2588 refill();
2589 }
2590 return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
2591 } else {
2592 return in.read();
2593 }
2594 }
2595
2596 public int read(byte[] b, int off, int len) throws IOException {
2597 return read(b, off, len, false);
2598 }
2599
2600 public long skip(long len) throws IOException {
2601 long remain = len;
2602 while (remain > 0) {
2603 if (blkmode) {
2604 if (pos == end) {
2605 refill();
2606 }
2607 if (end < 0) {
2608 break;
2609 }
2610 int nread = (int) Math.min(remain, end - pos);
2611 remain -= nread;
2612 pos += nread;
2613 } else {
2614 int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
2615 if ((nread = in.read(buf, 0, nread)) < 0) {
2616 break;
2617 }
2618 remain -= nread;
2619 }
2620 }
2621 return len - remain;
2622 }
2623
2624 public int available() throws IOException {
2625 if (blkmode) {
2626 if ((pos == end) && (unread == 0)) {
2627 int n;
2628 while ((n = readBlockHeader(false)) == 0) ;
2629 switch (n) {
2630 case HEADER_BLOCKED:
2631 break;
2632
2633 case -1:
2634 pos = 0;
2635 end = -1;
2636 break;
2637
2638 default:
2639 pos = 0;
2640 end = 0;
2641 unread = n;
2642 break;
2643 }
2644 }
2645
2646 int unreadAvail = (unread > 0) ?
2647 Math.min(in.available(), unread) : 0;
2648 return (end >= 0) ? (end - pos) + unreadAvail : 0;
2649 } else {
2650 return in.available();
2651 }
2652 }
2653
2654 public void close() throws IOException {
2655 if (blkmode) {
2656 pos = 0;
2657 end = -1;
2658 unread = 0;
2659 }
2660 in.close();
2661 }
2662
2663
2664
2665
2666
2667
2668
2669
2670 int read(byte[] b, int off, int len, boolean copy) throws IOException {
2671 if (len == 0) {
2672 return 0;
2673 } else if (blkmode) {
2674 if (pos == end) {
2675 refill();
2676 }
2677 if (end < 0) {
2678 return -1;
2679 }
2680 int nread = Math.min(len, end - pos);
2681 System.arraycopy(buf, pos, b, off, nread);
2682 pos += nread;
2683 return nread;
2684 } else if (copy) {
2685 int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
2686 if (nread > 0) {
2687 System.arraycopy(buf, 0, b, off, nread);
2688 }
2689 return nread;
2690 } else {
2691 return in.read(b, off, len);
2692 }
2693 }
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703 public void readFully(byte[] b) throws IOException {
2704 readFully(b, 0, b.length, false);
2705 }
2706
2707 public void readFully(byte[] b, int off, int len) throws IOException {
2708 readFully(b, off, len, false);
2709 }
2710
2711 public void readFully(byte[] b, int off, int len, boolean copy)
2712 throws IOException
2713 {
2714 while (len > 0) {
2715 int n = read(b, off, len, copy);
2716 if (n < 0) {
2717 throw new EOFException();
2718 }
2719 off += n;
2720 len -= n;
2721 }
2722 }
2723
2724 public int skipBytes(int n) throws IOException {
2725 return din.skipBytes(n);
2726 }
2727
2728 public boolean readBoolean() throws IOException {
2729 int v = read();
2730 if (v < 0) {
2731 throw new EOFException();
2732 }
2733 return (v != 0);
2734 }
2735
2736 public byte readByte() throws IOException {
2737 int v = read();
2738 if (v < 0) {
2739 throw new EOFException();
2740 }
2741 return (byte) v;
2742 }
2743
2744 public int readUnsignedByte() throws IOException {
2745 int v = read();
2746 if (v < 0) {
2747 throw new EOFException();
2748 }
2749 return v;
2750 }
2751
2752 public char readChar() throws IOException {
2753 if (!blkmode) {
2754 pos = 0;
2755 in.readFully(buf, 0, 2);
2756 } else if (end - pos < 2) {
2757 return din.readChar();
2758 }
2759 char v = Bits.getChar(buf, pos);
2760 pos += 2;
2761 return v;
2762 }
2763
2764 public short readShort() throws IOException {
2765 if (!blkmode) {
2766 pos = 0;
2767 in.readFully(buf, 0, 2);
2768 } else if (end - pos < 2) {
2769 return din.readShort();
2770 }
2771 short v = Bits.getShort(buf, pos);
2772 pos += 2;
2773 return v;
2774 }
2775
2776 public int readUnsignedShort() throws IOException {
2777 if (!blkmode) {
2778 pos = 0;
2779 in.readFully(buf, 0, 2);
2780 } else if (end - pos < 2) {
2781 return din.readUnsignedShort();
2782 }
2783 int v = Bits.getShort(buf, pos) & 0xFFFF;
2784 pos += 2;
2785 return v;
2786 }
2787
2788 public int readInt() throws IOException {
2789 if (!blkmode) {
2790 pos = 0;
2791 in.readFully(buf, 0, 4);
2792 } else if (end - pos < 4) {
2793 return din.readInt();
2794 }
2795 int v = Bits.getInt(buf, pos);
2796 pos += 4;
2797 return v;
2798 }
2799
2800 public float readFloat() throws IOException {
2801 if (!blkmode) {
2802 pos = 0;
2803 in.readFully(buf, 0, 4);
2804 } else if (end - pos < 4) {
2805 return din.readFloat();
2806 }
2807 float v = Bits.getFloat(buf, pos);
2808 pos += 4;
2809 return v;
2810 }
2811
2812 public long readLong() throws IOException {
2813 if (!blkmode) {
2814 pos = 0;
2815 in.readFully(buf, 0, 8);
2816 } else if (end - pos < 8) {
2817 return din.readLong();
2818 }
2819 long v = Bits.getLong(buf, pos);
2820 pos += 8;
2821 return v;
2822 }
2823
2824 public double readDouble() throws IOException {
2825 if (!blkmode) {
2826 pos = 0;
2827 in.readFully(buf, 0, 8);
2828 } else if (end - pos < 8) {
2829 return din.readDouble();
2830 }
2831 double v = Bits.getDouble(buf, pos);
2832 pos += 8;
2833 return v;
2834 }
2835
2836 public String readUTF() throws IOException {
2837 return readUTFBody(readUnsignedShort());
2838 }
2839
2840 public String readLine() throws IOException {
2841 return din.readLine();
2842 }
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852 void readBooleans(boolean[] v, int off, int len) throws IOException {
2853 int stop, endoff = off + len;
2854 while (off < endoff) {
2855 if (!blkmode) {
2856 int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
2857 in.readFully(buf, 0, span);
2858 stop = off + span;
2859 pos = 0;
2860 } else if (end - pos < 1) {
2861 v[off++] = din.readBoolean();
2862 continue;
2863 } else {
2864 stop = Math.min(endoff, off + end - pos);
2865 }
2866
2867 while (off < stop) {
2868 v[off++] = Bits.getBoolean(buf, pos++);
2869 }
2870 }
2871 }
2872
2873 void readChars(char[] v, int off, int len) throws IOException {
2874 int stop, endoff = off + len;
2875 while (off < endoff) {
2876 if (!blkmode) {
2877 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
2878 in.readFully(buf, 0, span << 1);
2879 stop = off + span;
2880 pos = 0;
2881 } else if (end - pos < 2) {
2882 v[off++] = din.readChar();
2883 continue;
2884 } else {
2885 stop = Math.min(endoff, off + ((end - pos) >> 1));
2886 }
2887
2888 while (off < stop) {
2889 v[off++] = Bits.getChar(buf, pos);
2890 pos += 2;
2891 }
2892 }
2893 }
2894
2895 void readShorts(short[] v, int off, int len) throws IOException {
2896 int stop, endoff = off + len;
2897 while (off < endoff) {
2898 if (!blkmode) {
2899 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
2900 in.readFully(buf, 0, span << 1);
2901 stop = off + span;
2902 pos = 0;
2903 } else if (end - pos < 2) {
2904 v[off++] = din.readShort();
2905 continue;
2906 } else {
2907 stop = Math.min(endoff, off + ((end - pos) >> 1));
2908 }
2909
2910 while (off < stop) {
2911 v[off++] = Bits.getShort(buf, pos);
2912 pos += 2;
2913 }
2914 }
2915 }
2916
2917 void readInts(int[] v, int off, int len) throws IOException {
2918 int stop, endoff = off + len;
2919 while (off < endoff) {
2920 if (!blkmode) {
2921 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
2922 in.readFully(buf, 0, span << 2);
2923 stop = off + span;
2924 pos = 0;
2925 } else if (end - pos < 4) {
2926 v[off++] = din.readInt();
2927 continue;
2928 } else {
2929 stop = Math.min(endoff, off + ((end - pos) >> 2));
2930 }
2931
2932 while (off < stop) {
2933 v[off++] = Bits.getInt(buf, pos);
2934 pos += 4;
2935 }
2936 }
2937 }
2938
2939 void readFloats(float[] v, int off, int len) throws IOException {
2940 int span, endoff = off + len;
2941 while (off < endoff) {
2942 if (!blkmode) {
2943 span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
2944 in.readFully(buf, 0, span << 2);
2945 pos = 0;
2946 } else if (end - pos < 4) {
2947 v[off++] = din.readFloat();
2948 continue;
2949 } else {
2950 span = Math.min(endoff - off, ((end - pos) >> 2));
2951 }
2952
2953 bytesToFloats(buf, pos, v, off, span);
2954 off += span;
2955 pos += span << 2;
2956 }
2957 }
2958
2959 void readLongs(long[] v, int off, int len) throws IOException {
2960 int stop, endoff = off + len;
2961 while (off < endoff) {
2962 if (!blkmode) {
2963 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
2964 in.readFully(buf, 0, span << 3);
2965 stop = off + span;
2966 pos = 0;
2967 } else if (end - pos < 8) {
2968 v[off++] = din.readLong();
2969 continue;
2970 } else {
2971 stop = Math.min(endoff, off + ((end - pos) >> 3));
2972 }
2973
2974 while (off < stop) {
2975 v[off++] = Bits.getLong(buf, pos);
2976 pos += 8;
2977 }
2978 }
2979 }
2980
2981 void readDoubles(double[] v, int off, int len) throws IOException {
2982 int span, endoff = off + len;
2983 while (off < endoff) {
2984 if (!blkmode) {
2985 span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
2986 in.readFully(buf, 0, span << 3);
2987 pos = 0;
2988 } else if (end - pos < 8) {
2989 v[off++] = din.readDouble();
2990 continue;
2991 } else {
2992 span = Math.min(endoff - off, ((end - pos) >> 3));
2993 }
2994
2995 bytesToDoubles(buf, pos, v, off, span);
2996 off += span;
2997 pos += span << 3;
2998 }
2999 }
3000
3001
3002
3003
3004
3005
3006 String readLongUTF() throws IOException {
3007 return readUTFBody(readLong());
3008 }
3009
3010
3011
3012
3013
3014
3015 private String readUTFBody(long utflen) throws IOException {
3016 StringBuilder sbuf = new StringBuilder();
3017 if (!blkmode) {
3018 end = pos = 0;
3019 }
3020
3021 while (utflen > 0) {
3022 int avail = end - pos;
3023 if (avail >= 3 || (long) avail == utflen) {
3024 utflen -= readUTFSpan(sbuf, utflen);
3025 } else {
3026 if (blkmode) {
3027
3028 utflen -= readUTFChar(sbuf, utflen);
3029 } else {
3030
3031 if (avail > 0) {
3032 System.arraycopy(buf, pos, buf, 0, avail);
3033 }
3034 pos = 0;
3035 end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
3036 in.readFully(buf, avail, end - avail);
3037 }
3038 }
3039 }
3040
3041 return sbuf.toString();
3042 }
3043
3044
3045
3046
3047
3048
3049
3050 private long readUTFSpan(StringBuilder sbuf, long utflen)
3051 throws IOException
3052 {
3053 int cpos = 0;
3054 int start = pos;
3055 int avail = Math.min(end - pos, CHAR_BUF_SIZE);
3056
3057 int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
3058 boolean outOfBounds = false;
3059
3060 try {
3061 while (pos < stop) {
3062 int b1, b2, b3;
3063 b1 = buf[pos++] & 0xFF;
3064 switch (b1 >> 4) {
3065 case 0:
3066 case 1:
3067 case 2:
3068 case 3:
3069 case 4:
3070 case 5:
3071 case 6:
3072 case 7:
3073 cbuf[cpos++] = (char) b1;
3074 break;
3075
3076 case 12:
3077 case 13:
3078 b2 = buf[pos++];
3079 if ((b2 & 0xC0) != 0x80) {
3080 throw new UTFDataFormatException();
3081 }
3082 cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
3083 ((b2 & 0x3F) << 0));
3084 break;
3085
3086 case 14:
3087 b3 = buf[pos + 1];
3088 b2 = buf[pos + 0];
3089 pos += 2;
3090 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3091 throw new UTFDataFormatException();
3092 }
3093 cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
3094 ((b2 & 0x3F) << 6) |
3095 ((b3 & 0x3F) << 0));
3096 break;
3097
3098 default:
3099 throw new UTFDataFormatException();
3100 }
3101 }
3102 } catch (ArrayIndexOutOfBoundsException ex) {
3103 outOfBounds = true;
3104 } finally {
3105 if (outOfBounds || (pos - start) > utflen) {
3106
3107
3108
3109
3110
3111 pos = start + (int) utflen;
3112 throw new UTFDataFormatException();
3113 }
3114 }
3115
3116 sbuf.append(cbuf, 0, cpos);
3117 return pos - start;
3118 }
3119
3120
3121
3122
3123
3124
3125
3126
3127 private int readUTFChar(StringBuilder sbuf, long utflen)
3128 throws IOException
3129 {
3130 int b1, b2, b3;
3131 b1 = readByte() & 0xFF;
3132 switch (b1 >> 4) {
3133 case 0:
3134 case 1:
3135 case 2:
3136 case 3:
3137 case 4:
3138 case 5:
3139 case 6:
3140 case 7:
3141 sbuf.append((char) b1);
3142 return 1;
3143
3144 case 12:
3145 case 13:
3146 if (utflen < 2) {
3147 throw new UTFDataFormatException();
3148 }
3149 b2 = readByte();
3150 if ((b2 & 0xC0) != 0x80) {
3151 throw new UTFDataFormatException();
3152 }
3153 sbuf.append((char) (((b1 & 0x1F) << 6) |
3154 ((b2 & 0x3F) << 0)));
3155 return 2;
3156
3157 case 14:
3158 if (utflen < 3) {
3159 if (utflen == 2) {
3160 readByte();
3161 }
3162 throw new UTFDataFormatException();
3163 }
3164 b2 = readByte();
3165 b3 = readByte();
3166 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3167 throw new UTFDataFormatException();
3168 }
3169 sbuf.append((char) (((b1 & 0x0F) << 12) |
3170 ((b2 & 0x3F) << 6) |
3171 ((b3 & 0x3F) << 0)));
3172 return 3;
3173
3174 default:
3175 throw new UTFDataFormatException();
3176 }
3177 }
3178 }
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209 private static class HandleTable {
3210
3211
3212 private static final byte STATUS_OK = 1;
3213 private static final byte STATUS_UNKNOWN = 2;
3214 private static final byte STATUS_EXCEPTION = 3;
3215
3216
3217 byte[] status;
3218
3219 Object[] entries;
3220
3221 HandleList[] deps;
3222
3223 int lowDep = -1;
3224
3225 int size = 0;
3226
3227
3228
3229
3230 HandleTable(int initialCapacity) {
3231 status = new byte[initialCapacity];
3232 entries = new Object[initialCapacity];
3233 deps = new HandleList[initialCapacity];
3234 }
3235
3236
3237
3238
3239
3240
3241
3242 int assign(Object obj) {
3243 if (size >= entries.length) {
3244 grow();
3245 }
3246 status[size] = STATUS_UNKNOWN;
3247 entries[size] = obj;
3248 return size++;
3249 }
3250
3251
3252
3253
3254
3255
3256
3257 void markDependency(int dependent, int target) {
3258 if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
3259 return;
3260 }
3261 switch (status[dependent]) {
3262
3263 case STATUS_UNKNOWN:
3264 switch (status[target]) {
3265 case STATUS_OK:
3266
3267 break;
3268
3269 case STATUS_EXCEPTION:
3270
3271 markException(dependent,
3272 (ClassNotFoundException) entries[target]);
3273 break;
3274
3275 case STATUS_UNKNOWN:
3276
3277 if (deps[target] == null) {
3278 deps[target] = new HandleList();
3279 }
3280 deps[target].add(dependent);
3281
3282
3283 if (lowDep < 0 || lowDep > target) {
3284 lowDep = target;
3285 }
3286 break;
3287
3288 default:
3289 throw new InternalError();
3290 }
3291 break;
3292
3293 case STATUS_EXCEPTION:
3294 break;
3295
3296 default:
3297 throw new InternalError();
3298 }
3299 }
3300
3301
3302
3303
3304
3305
3306
3307 void markException(int handle, ClassNotFoundException ex) {
3308 switch (status[handle]) {
3309 case STATUS_UNKNOWN:
3310 status[handle] = STATUS_EXCEPTION;
3311 entries[handle] = ex;
3312
3313
3314 HandleList dlist = deps[handle];
3315 if (dlist != null) {
3316 int ndeps = dlist.size();
3317 for (int i = 0; i < ndeps; i++) {
3318 markException(dlist.get(i), ex);
3319 }
3320 deps[handle] = null;
3321 }
3322 break;
3323
3324 case STATUS_EXCEPTION:
3325 break;
3326
3327 default:
3328 throw new InternalError();
3329 }
3330 }
3331
3332
3333
3334
3335
3336
3337 void finish(int handle) {
3338 int end;
3339 if (lowDep < 0) {
3340
3341 end = handle + 1;
3342 } else if (lowDep >= handle) {
3343
3344 end = size;
3345 lowDep = -1;
3346 } else {
3347
3348 return;
3349 }
3350
3351
3352 for (int i = handle; i < end; i++) {
3353 switch (status[i]) {
3354 case STATUS_UNKNOWN:
3355 status[i] = STATUS_OK;
3356 deps[i] = null;
3357 break;
3358
3359 case STATUS_OK:
3360 case STATUS_EXCEPTION:
3361 break;
3362
3363 default:
3364 throw new InternalError();
3365 }
3366 }
3367 }
3368
3369
3370
3371
3372
3373
3374
3375 void setObject(int handle, Object obj) {
3376 switch (status[handle]) {
3377 case STATUS_UNKNOWN:
3378 case STATUS_OK:
3379 entries[handle] = obj;
3380 break;
3381
3382 case STATUS_EXCEPTION:
3383 break;
3384
3385 default:
3386 throw new InternalError();
3387 }
3388 }
3389
3390
3391
3392
3393
3394
3395 Object lookupObject(int handle) {
3396 return (handle != NULL_HANDLE &&
3397 status[handle] != STATUS_EXCEPTION) ?
3398 entries[handle] : null;
3399 }
3400
3401
3402
3403
3404
3405
3406 ClassNotFoundException lookupException(int handle) {
3407 return (handle != NULL_HANDLE &&
3408 status[handle] == STATUS_EXCEPTION) ?
3409 (ClassNotFoundException) entries[handle] : null;
3410 }
3411
3412
3413
3414
3415 void clear() {
3416 Arrays.fill(status, 0, size, (byte) 0);
3417 Arrays.fill(entries, 0, size, null);
3418 Arrays.fill(deps, 0, size, null);
3419 lowDep = -1;
3420 size = 0;
3421 }
3422
3423
3424
3425
3426 int size() {
3427 return size;
3428 }
3429
3430
3431
3432
3433 private void grow() {
3434 int newCapacity = (entries.length << 1) + 1;
3435
3436 byte[] newStatus = new byte[newCapacity];
3437 Object[] newEntries = new Object[newCapacity];
3438 HandleList[] newDeps = new HandleList[newCapacity];
3439
3440 System.arraycopy(status, 0, newStatus, 0, size);
3441 System.arraycopy(entries, 0, newEntries, 0, size);
3442 System.arraycopy(deps, 0, newDeps, 0, size);
3443
3444 status = newStatus;
3445 entries = newEntries;
3446 deps = newDeps;
3447 }
3448
3449
3450
3451
3452 private static class HandleList {
3453 private int[] list = new int[4];
3454 private int size = 0;
3455
3456 public HandleList() {
3457 }
3458
3459 public void add(int handle) {
3460 if (size >= list.length) {
3461 int[] newList = new int[list.length << 1];
3462 System.arraycopy(list, 0, newList, 0, list.length);
3463 list = newList;
3464 }
3465 list[size++] = handle;
3466 }
3467
3468 public int get(int index) {
3469 if (index >= size) {
3470 throw new ArrayIndexOutOfBoundsException();
3471 }
3472 return list[index];
3473 }
3474
3475 public int size() {
3476 return size;
3477 }
3478 }
3479 }
3480
3481
3482
3483
3484 private static Object cloneArray(Object array) {
3485 if (array instanceof Object[]) {
3486 return ((Object[]) array).clone();
3487 } else if (array instanceof boolean[]) {
3488 return ((boolean[]) array).clone();
3489 } else if (array instanceof byte[]) {
3490 return ((byte[]) array).clone();
3491 } else if (array instanceof char[]) {
3492 return ((char[]) array).clone();
3493 } else if (array instanceof double[]) {
3494 return ((double[]) array).clone();
3495 } else if (array instanceof float[]) {
3496 return ((float[]) array).clone();
3497 } else if (array instanceof int[]) {
3498 return ((int[]) array).clone();
3499 } else if (array instanceof long[]) {
3500 return ((long[]) array).clone();
3501 } else if (array instanceof short[]) {
3502 return ((short[]) array).clone();
3503 } else {
3504 throw new AssertionError();
3505 }
3506 }
3507
3508 }